
#include "util.h"

#include <stdio.h>

#include <v8.h>

using namespace v8;

namespace js {

/**
 * Loads, compiles and runs script from the file specified.
 * \param file_name Source file.
 * \returns Zero if the file was loaded, negative value otherwise.
 */
int run_js_script(const char * file_name) {
    int result = 0;

    FILE * f = fopen(file_name, "rb");

    // TODO: inversion of control to get rid of the deep nesting
    if (f != NULL) {
        fseek(f, 0, SEEK_END);
        size_t file_size = static_cast<size_t>(ftell(f));
        fseek(f, 0, SEEK_SET);

        char * buffer = new char[file_size];

        size_t bytes_read = fread(buffer, 1, file_size, f);
        if (bytes_read == file_size) {
            // compile and execute what is loaded
            Handle<Script> script;

            {
                TryCatch try_catch;
                script = Script::Compile(String::New(buffer, bytes_read), String::New(file_name));
                if (script.IsEmpty()) {
                    Handle<Value> exception = try_catch.Exception();
                    String::AsciiValue exception_str(exception);
                    fprintf(stderr, "Exception while compiling %s: %s\n", file_name, *exception_str);
                    result = -1;
                }
            }

            if (!result)
            {
                TryCatch try_catch;
                Handle<Value> eval_result = script->Run();
                if (eval_result.IsEmpty()) {
                    Handle<Value> exception = try_catch.Exception();
                    String::AsciiValue exception_str(exception);
                    fprintf(stderr, "Exception while running %s: %s\n", file_name, *exception_str);
                    result = -2;
                }
            }

        }
        else {
            fprintf(stderr, "Error while reading %s\n", file_name);
            result = -3;
        }

        delete [] buffer;
        fclose(f);
    }
    else {
        fprintf(stderr, "Can't open %s for reading\n", file_name);
        result = -4;
    }

    return result;
}

} // namespace js
